<html>
<head>
<title>CpcPaChi - Version 0.06</title>
<style type="text/css">
span {
  font-family: 'Courier New';
  font-size: 10pt;
  color: #000000;
}
.sc0 {
  color: #808080;
}
.sc3 {
  color: #008080;
}
.sc4 {
  color: #FF8000;
}
.sc5 {
  font-weight: bold;
  color: #0000FF;
}
.sc7 {
  color: #808080;
}
.sc9 {
  color: #804000;
}
.sc10 {
  font-weight: bold;
  color: #000080;
}
.sc11 {
}
</style>
</head>
<body>
<h2>Un compilador sencillo paso a paso (6 - Nuevas &oacute;rdenes)</h2>

<p align="right">(Volver al <a href="doc.html">&iacute;ndice</a>) </p>

<p>Sigamos ampliando nuestro compilador elemental. Nos queda mucho por hacer. Algunas cosas ser&aacute;n relativamente trabajosas, como declarar y usar variables, o m&aacute;s todav&iacute;a cuando queramos crear procedimientos, pero alg&uacute;n otro detalle es sencillo, como seguir a&ntilde;adiendo nuevas &oacute;rdenes simples.</p>

<p>Comenzaremos por ah&iacute;: vamos a a&ntilde;adir tres &oacute;rdenes nuevas, que permitan cambiar el modo de pantalla, el color del texto y el color de fondo.</p>

<ul>
  <li>La orden de cambiar un modo de pantalla ser&aacute; "CpcMode", que recibir&aacute; un &uacute;nico par&aacute;metro: el n&uacute;mero de modo (0 para 20 columnas y 16 colores, 1 para 40 columnas y 4 colores, 2 para 80 columnas y 2 colores). Le pondremos el prefijo "Cpc" por eso de que es una orden "casi exclusiva de los CPC", mientras que las anteriores (cls, locate, writechar) tendr&iacute;an  sentido en casi cualquier sistema inform&aacute;tico.</li>

  <li>Las &oacute;rdenes de cambiar color, como tambi&eacute;n existir&aacute;n para casi cualquier sistema, no tendr&aacute;n el prefijo "cpc", y seguir&aacute;n la nomenclatura que se usaba en el Basic de estos equipos: PEN para cambiar el color de escritura (pluma) y PAPER para el color de fondo (papel).</li>
</ul>

<p>As&iacute;, al generador de c&oacute;digo (uPachiG) bastar&iacute;a con a&ntilde;adirle las correspondientes llamadas a rutinas del firmware:</p>

<pre><code>
/* Generar codigo para CPCMODE */
public void genCPCMODE( int modo )
{
    ficheroDestino.WriteLine(lineaActual
      + &quot; DATA 3E,&quot; + Convert.ToString(modo,16).ToUpper()
      + &quot;: ' LD A, \&quot;&quot; + modo +&quot;\&quot;&quot;);
    lineaActual += 10;
    ficheroDestino.WriteLine(lineaActual+
      &quot; DATA CD,0E,BC: ' CALL &amp;BC0E - SET MODE&quot; );
    lineaActual += 10;
    longitudTotal += 5;
}


/* Generar codigo para CPCPAPER */
public void genCPCPAPER( int color )
{
    ficheroDestino.WriteLine(lineaActual
      + &quot; DATA 3E,&quot; + Convert.ToString(color,16).ToUpper()
      + &quot;: ' LD A, \&quot;&quot; + color +&quot;\&quot;&quot;);
    lineaActual += 10;
    ficheroDestino.WriteLine(lineaActual+
      &quot; DATA CD,96,BB: ' CALL &amp;BB96 - SET PAPER&quot; );
    lineaActual += 10;
    longitudTotal += 5;
}


/* Generar codigo para CPCPEN */
public void genCPCPEN( int color )
{
    ficheroDestino.WriteLine(lineaActual
      + &quot; DATA 3E,&quot; + Convert.ToString(color,16).ToUpper()
      + &quot;: ' LD A, \&quot;&quot; + color +&quot;\&quot;&quot;);
    lineaActual += 10;
    ficheroDestino.WriteLine(lineaActual+
      &quot; DATA CD,90,BB: ' CALL &amp;BB90 - SET PEN&quot; );
    lineaActual += 10;
    longitudTotal += 5;
}
</code></pre>



<p>En el analizador sint&aacute;ctico, los cambios son peque&ntilde;os tambi&eacute;n. Aun as&iacute;, podemos aprovechar para hacerlo un poco m&aacute;s modular: los detalles del an&aacute;lisis no deber&iacute;an estar todos dentro  del procedimiento "analizarCualquierOrden", sino que &eacute;ste deber&iacute;a delegar en otros, as&iacute;:</p>

<pre><code>
void analizarCualquierOrden()
{
  string orden = miLexer.ObtenerIdentificador().ToUpper();

  if (depurando)
    Console.WriteLine(&quot;Analizando: {0}&quot;, orden);

  if (orden == null)
  {
    analisisTerminado = true;
    return;
  }

  switch (orden)
  {
    case &quot;CLS&quot;: analizarCLS(); break;
    case &quot;CPCMODE&quot;: analizarCPCMODE(); break;
    case &quot;LOCATE&quot;: analizarLOCATE(); break;
    ...

  [...]

void analizarCLS()
{
  miLexer.LeerSimbolo(';');
  miGenerador.genCLS();
}

void analizarCPCMODE()
{
  miLexer.LeerSimbolo('(');
  int modo = miLexer.ObtenerEntero();
  miLexer.LeerSimbolo(')');
  miLexer.LeerSimbolo(';');
  miGenerador.genCPCMODE( modo );
}
...
</code></pre>

<p>De igual modo, podemos aprovechar para hacer una peque&ntilde;a mejora
en el cuerpo del programa: que el nombre del fichero de salida
no sea &quot;salida.bas&quot;, sino que se cree a partir del fichero de
entrada, reemplazando &quot;.pas&quot; por &quot;.bas&quot; (por ejemplo, a partor
de &quot;ejemplo6.pas&quot; se crear&iacute;a &quot;ejemplo6.bas&quot;).</p>

<pre><code>
nombreOrigen = opciones[0];
miLexer = new Lexer(nombreOrigen);
// Creo el nombre de destino cambiando .pas por .bas
string nombreDestino = nombreOrigen;
if (nombreDestino.IndexOf(&quot;.&quot;) &gt; 0)
  nombreDestino = nombreDestino.Remove (nombreDestino.IndexOf(&quot;.&quot;) );
nombreDestino += &quot;.bas&quot;;
miGenerador = new CodeGen(  nombreDestino );
</code></pre>


<p><br>Como siempre, para m&aacute;s detalles, todo el c&oacute;digo est&aacute; en la p&aacute;gina del proyecto en Google Code:<br /><br /><a href="http://code.google.com/p/cpcpachi/">http://code.google.com/p/cpcpachi/</a></p>



<p align="right">(Volver al <a href="doc.html">&iacute;ndice</a>) </p>
</body>
</html>
